package net.obxlabs.tweetpad;

import java.util.*;
import net.silentlycrashing.util.*;
import twitter4j.*;

public class Mailman extends Thread {
	public static final int BUFFER_MIN = 10;
	
	private Sketchpad p;
	private Twitter twitter;
	private List<Tweet> bufferedTweets = Collections.synchronizedList(new LinkedList<Tweet>());
    private RegisteredAction onLoad;
	private int pollInterval;
	private int bufferSize;
	private int lastTweetId;
	
	public Mailman(Sketchpad p) {
		this(p, 1000*30, 20);  // poll every 30 seconds
	}
	
	public Mailman(Sketchpad p, int pollInterval, int bufferSize) {
		this.p = p;
		this.pollInterval = pollInterval;
		this.bufferSize = bufferSize;
		lastTweetId = 0;
		twitter = new Twitter();
	}
	
	public void start(String name) {
        setName(name);
        setDaemon(true);
        start();
    }
	
	public void run() {
        while (true) {
            try {
                if (bufferedTweets.size() <= BUFFER_MIN) {
                	loadTweets();
                	//printTweets();
                }
                Thread.sleep(pollInterval);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (TwitterException e) {
            	handleTwitterException(e);
            }
        }
    }
	
	public void loadTweets() throws TwitterException {
		// get the data from the Twitter server
		List<Status> tempStatuses;
		Tweet tempTweet;
		if (lastTweetId == 0) {
			tempStatuses = twitter.getPublicTimeline();
			
			// only consider the last statuses if the List is too long
			if (tempStatuses.size() > bufferSize) {
				tempStatuses.subList(0, bufferSize);
			}
			
			// build the Tweets and add them to the end of the List
			for (Status tempStatus : tempStatuses) {
				try {
					tempTweet = new Tweet(p, tempStatus);
					bufferedTweets.add(tempTweet);
				} catch (NullPointerException e) {
					// something's wrong, skip this entry
				}
			}
		} else {
			tempStatuses = twitter.getPublicTimeline(lastTweetId);
			
			// only consider the last statuses if the List is too long
			if (tempStatuses.size() > bufferSize) {
				tempStatuses.subList(0, bufferSize);
			}
			
			// build the Tweets and add them to the beginning of the List
			for (ListIterator<Status> i = tempStatuses.listIterator(tempStatuses.size()); i.hasPrevious();) {
				try {
					tempTweet = new Tweet(p, i.previous());
					bufferedTweets.add(tempTweet);
				} catch (NullPointerException e) {
					// something's wrong, skip this entry
				}
			}
		}
		
		lastTweetId = bufferedTweets.get(0).getTextId();
		
		// call onLoad action
		if (onLoad != null) {
			onLoad.invoke();
		}
	}
	
	public void handleTwitterException(TwitterException e) {
    	e.printStackTrace();
    	
    	//switch (method) {
    	//	case AsyncTwitter.USER_TIMELINE:
    	//	case AsyncTwitter.USER_DETAIL:
    	//		break;
    	//	default:
    	//		statusLabel.setValue("Twitter error "+method);
    	//}
    }
	
	public void printTweets() {
		System.out.println("*******************");
		for (Tweet tweet : bufferedTweets) {
			System.out.println(tweet.getScreenName()+"\t\t"+tweet.getUpdateTime()+"\t\t"+tweet.getText());
		}
	}
	
	public void setOnLoadAction(String method, Object object) {
		onLoad = new RegisteredAction(method, object);
	}
	
	public synchronized boolean hasMore() {
		return (bufferedTweets.size() > 0);
	}
	
	public synchronized Tweet getTweet() {
		return bufferedTweets.remove(bufferedTweets.size()-1);
	}
}
